Skip to content

feat(ink-compat): remove third-party Ink deps and fill Gemini compat gaps#32

Merged
RtlZeroMemory merged 3 commits intomainfrom
feat/ink-compat-gemini-surface-parity
Feb 11, 2026
Merged

feat(ink-compat): remove third-party Ink deps and fill Gemini compat gaps#32
RtlZeroMemory merged 3 commits intomainfrom
feat/ink-compat-gemini-surface-parity

Conversation

@RtlZeroMemory
Copy link
Copy Markdown
Owner

Summary

This PR wires missing @rezi-ui/ink-compat compatibility surface for Gemini usage and removes third-party Ink/Ink-related dependencies from the compat package itself.

What changed

  • Removed third-party Ink dependencies from packages/ink-compat/package.json.
    • Removed ink, ink-spinner, ink-gradient, and @alcalzone/ansi-tokenize usage from compat implementation/deps.
    • Kept only react-reconciler runtime dependency.
  • Added native styled-text compatibility implementation:
    • New packages/ink-compat/src/styledTextCompat.ts
    • Exported via packages/ink-compat/src/index.ts
  • Expanded API surface used by Gemini:
    • getInnerWidth added/exported (measurement.ts, measureElement.ts, index.ts)
    • BoxProps/TextProps additions (types.ts): max constraints, backgroundColor, sticky-ish/userSelect/opaque fields, a11y-ish fields.
    • DOMElement shape extended (types.ts) including yogaNode field.
    • Box ref typing updated to DOMElement (components/Box.tsx).
  • App context/rerender plumbing:
    • AppContext now includes rerender (context/AppContext.ts)
    • useApp returns AppProps including rerender (hooks/useApp.ts)
    • Render pipeline wires rerender callback (render.ts)
  • React 19/reconciler host config adaptation:
    • Added update-priority/transition-related host config methods and missing runtime hooks (reconciler/hostConfig.ts).
  • Compat test updates:
    • Updated tests for new AppContext shape and styled-text exports.
    • Replaced third-party compat test imports with internal compatibility scenarios (compat.thirdparty.test.tsx).

Validation run

  • npx tsc -b packages/ink-compat
  • npm ls -w @rezi-ui/ink-compat ink ink-spinner ink-gradient @jrichman/ink @alcalzone/ansi-tokenize (expected empty for compat package) ✅
  • Focused test run:
    • node --test --test-concurrency=1 packages/ink-compat/dist/__tests__/Newline.test.js packages/ink-compat/dist/__tests__/useApp.test.js packages/ink-compat/dist/__tests__/measurement.test.js packages/ink-compat/dist/__tests__/integration/counter.test.js packages/ink-compat/dist/__tests__/Static.test.js
    • Result: partial pass + remaining failures (see blockers below) ❌

Remaining blockers

React 19 + current react-reconciler behavior still leaves unresolved runtime parity gaps:

  • useApp/useStdin “outside render root” assertion timing differs (errors become asynchronous in tests).
  • Focus/input integration parity incomplete in test harness (integration/counter, focus cycle/list nav).
  • Measurement/resize observer expectations fail in several scenarios.
  • Static accumulation duplicates in one scenario.

These are tracked here as explicit blockers so we can continue iterating without reintroducing third-party Ink dependencies.

@RtlZeroMemory
Copy link
Copy Markdown
Owner Author

Update: I iterated on the remaining React 19 runtime blockers and pushed commit e691eec.

What was fixed in this iteration:

  • Corrected React 19 host config update semantics:
    • commitUpdate now uses (instance, type, oldProps, newProps) and applies newProps (previously props were corrupted on rerender).
  • Added deterministic reconciler flush/sync utilities in reconciler.ts:
    • container-scoped error capture + synchronous rethrow in updateRootContainer.
    • flushAllUpdates() and runWithSyncPriority() helpers.
  • Wired input emitter delivery through sync-priority execution:
    • internal/emitter.ts now runs listeners inside reconciler sync context.
  • Updated focus state transitions to use sync-priority updates:
    • context/FocusProvider.tsx now routes focus-related state updates through runWithSyncPriority.
  • Testing utility integration:
    • testing/simulateKeyEvent.ts continues to flush after event dispatch.

Validation now:

  • npx tsc -b packages/ink-compat
  • Full package test run:
    • node --test --test-concurrency=1 $(rg --files packages/ink-compat/dist | rg '__tests__/.*\\.test\\.js$' | sort)
    • Result: # pass 78, # fail 0

Gemini startup smoke (local patched package injection for validation) still reaches first frame:

  • observed terminal title/status: ◇ Ready (cli) in startup log.

@RtlZeroMemory RtlZeroMemory marked this pull request as ready for review February 11, 2026 12:38
@RtlZeroMemory RtlZeroMemory merged commit 36219f4 into main Feb 11, 2026
14 checks passed
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 211fb05c86

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +113 to 115
prepareUpdate(_instance: Instance, _type: HostType, _oldProps: Props, _newProps: Props) {
return null;
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Return update signal from prepareUpdate for prop changes

prepareUpdate now always returns null, which tells React there is no host update and prevents commitUpdate from running for changed element props. As a result, rerenders that modify host props (for example <Box> width/height/scrollTop or <Text> style props) keep stale attributes in the host tree even though the React tree changed, breaking measurement and scroll behavior after updates. Return a non-null payload when props change (as before) so commitUpdate is actually invoked.

Useful? React with 👍 / 👎.

@RtlZeroMemory RtlZeroMemory deleted the feat/ink-compat-gemini-surface-parity branch February 19, 2026 17:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants